package com.xms.security.service.sitemap;

import com.xms.security.entity.Privilege;
import com.xms.utils.CollectionUtil;
import com.xms.utils.JsonUtil;
import com.xms.utils.StringUtil;
import com.xms.utils.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * PrivilegeTreeBuilder
 * </p>
 *
 * @author migo
 * @since 2021/9/9
 */
@Service
public class PrivilegeTreeBuilder implements IPrivilegeTreeBuilder{
    private IPrivilegeFinderService _privilegeFinderService;
    @Autowired
    public PrivilegeTreeBuilder(IPrivilegeFinderService privilegeFinderService)
    {
        _privilegeFinderService = privilegeFinderService;
    }

    @Override
    public List<Privilege> getTreePath(String url)
    {
        if (StringUtil.notEmpty(url))
        {
            Predicate<Privilege> filter = (n -> n.getUrl().equalsIgnoreCase(url));
            return getTreePathCore(filter);
        }
        return null;
    }

    @Override
    public List<Privilege> getTreePath(String areaName, String className, String methodName)
    {
        if (StringUtil.notEmpty(className) && StringUtil.notEmpty(methodName))
        {
            Predicate<Privilege> filter = (n -> n.getClassname().equalsIgnoreCase(className) && n.getMethodname().equalsIgnoreCase(methodName));
            if (StringUtil.notEmpty(areaName))
            {
                filter.and(x -> x.getSystemname().equalsIgnoreCase(areaName));
            }
            return getTreePathCore(filter);
        }
        return null;
    }

    private List<Privilege> getTreePathCore(Predicate<Privilege> filter)
    {
        List<Privilege> result = new ArrayList<>();
        List<Privilege> all = _privilegeFinderService.all();
        if (all == null)
        {
            return result;
        }
        Privilege current = all.stream().filter(filter).findFirst().orElse(null);
        if (null != current)
        {
            boolean flag = current.getLevel() > 1;
            result.add(current);
            UUID parentid = current.getParentprivilegeid();
            while (flag)
            {
                UUID finalParentid = parentid;
                Privilege parent = all.stream().filter(n -> n.getPrivilegeid().equals(finalParentid)).findFirst().orElse(null);
                if (parent != null)
                {
                    result.add(parent);
                    parentid = parent.getParentprivilegeid();
                    if (parent.getLevel() <= 1)
                    {
                        flag = false;
                    }
                }
                else
                {
                    flag = false;
                }
            }
            Collections.reverse(result);
        }

        return result;
    }

    @Override
    public String build(Boolean onlyVisibled)
    {
        List<Privilege> list = (onlyVisibled == null || !onlyVisibled ?
                _privilegeFinderService.all() : _privilegeFinderService.getVisibled());

        List<HashMap<String, Object>> dlist = build(list, UUIDUtil.Empty);
        HashMap<String, Object> contact = new HashMap<>();
        contact.put("id", UUIDUtil.Empty);
        contact.put("label", "root");
        contact.put("children", dlist);

        List<HashMap<String, Object>> results = new ArrayList<>();
        results.add(contact);

        String json = JsonUtil.toJSONString(results);
        return json;
    }

    @Override
    public List<HashMap<String, Object>> build(List<Privilege> privilegeList, UUID parentId)
    {
        if(CollectionUtil.isEmpty(privilegeList)){
            return null;
        }
        List<HashMap<String, Object>> dynamicList = new ArrayList<>();
        List<Privilege> childList = privilegeList.stream().filter(n -> n.getParentprivilegeid().equals(parentId)).collect(Collectors.toList());

        if (childList != null && childList.size() > 0)
        {
            List<HashMap<String, Object>> ddList;
            for (Privilege item : childList)
            {
                HashMap<String, Object> contact = new HashMap<>();
                contact.put("label", item.getDisplayname());
                contact.put("id", item.getPrivilegeid());
                contact.put("url", item.getUrl());
                contact.put("smallicon", item.getSmallicon());
                contact.put("opentarget", item.getOpentarget());
                if (privilegeList.stream().anyMatch(n -> n.getParentprivilegeid().equals(item.getPrivilegeid())))
                {
                    ddList = build(privilegeList, item.getPrivilegeid());
                    if (ddList.size() > 0)
                    {
                        contact.put("children", ddList);
                        ddList = new ArrayList<>();
                    }
                }
                dynamicList.add(contact);
            }
        }
        return dynamicList;
    }
}
